//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package pxb.android.zipalign;

import java.io.Closeable;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;

public class FastZipOut implements Closeable {
    static Method Inflater_setInput;
    static Method Inflater_inflate;
    static Method CRC32_update;
    private final FileChannel outChannel;
    private final RandomAccessFile raf;
    private int targetSdk = 0;
    List<FastZipEntry> freshEntries = new ArrayList();

    public void setTargetSdk(int targetSdk) {
        this.targetSdk = targetSdk;
    }

    public FastZipOut(File out) throws IOException {
        this.raf = new RandomAccessFile(out, "rw");
        this.raf.setLength(0L);
        this.outChannel = this.raf.getChannel();
    }

    private static int calcPadding(long pos, int align) {
        int x = (int)(pos % (long)align);
        return x != 0 ? align - x : 0;
    }

    private static ByteBuffer getContent0(Source source, FastZipEntry entry) throws IOException, DataFormatException {
        ByteBuffer raw = source.getRaw(entry);
        if (entry.compressionMethod == 0) {
            return raw;
        } else {
            ByteBuffer out = ByteBuffer.allocate((int)entry.unCompressSize);
            ByteBuffer out0 = out.slice();
            inflate(raw, out0);
            if (out0.hasRemaining()) {
                throw new IOException("Size mismatch on inflated file: " + out.position() + " vs " + entry.unCompressSize);
            } else {
                return out;
            }
        }
    }

    public static ByteBuffer getContent(Source source, FastZipEntry entry) throws IOException, DataFormatException {
        ByteBuffer raw = getContent0(source, entry);
        long crc32Value = crc(raw);
        if (crc32Value != entry.crc) {
            throw new IOException("crc mismatch on inflated file: " + crc32Value + " vs " + entry.crc);
        } else {
            return raw;
        }
    }

    private static void localFileHeader(FastZipEntry e, FileChannel s, int aligment) throws IOException {
        byte[] bName = e.name;
        int headerSize = 30;
        int padding = calcPadding(s.position() + (long)headerSize + (long)bName.length, aligment);
        ByteBuffer b = ByteBuffer.allocate(headerSize).order(ByteOrder.LITTLE_ENDIAN);
        b.putInt(67324752);
        b.putShort((short)0);
        b.putShort((short)e.gpbf);
        b.putShort((short)e.compressionMethod);
        b.putInt((int)e.modTime);
        b.putInt((int)e.crc);
        b.putInt((int)e.compressedSize);
        b.putInt((int)e.unCompressSize);
        b.putShort((short)bName.length);
        b.putShort((short)padding);
        if (b.hasRemaining()) {
            throw new RuntimeException();
        } else {
            b.rewind();
            s.write(b);
            s.write(ByteBuffer.wrap(bName));
            if (padding != 0) {
                s.write(ByteBuffer.allocate(padding));
            }

        }
    }

    private static void ceFileHeader(FastZipEntry e, FileChannel s) throws IOException {
        byte[] bName = e.name;
        int headerSize = 46;
        ByteBuffer b = ByteBuffer.allocate(headerSize).order(ByteOrder.LITTLE_ENDIAN);
        b.putInt(33639248);
        b.putShort((short)0);
        b.putShort((short)0);
        b.putShort((short)e.gpbf);
        b.putShort((short)e.compressionMethod);
        b.putInt((int)e.modTime);
        b.putInt((int)e.crc);
        b.putInt((int)e.compressedSize);
        b.putInt((int)e.unCompressSize);
        b.putShort((short)bName.length);
        b.putShort((short)0);
        b.putShort((short)0);
        b.putShort((short)0);
        b.putShort((short)0);
        b.putShort((short)0);
        b.putShort((short)0);
        b.putInt((int)e.localHeaderRelOffset);
        if (b.hasRemaining()) {
            throw new RuntimeException();
        } else {
            b.rewind();
            s.write(b);
            s.write(ByteBuffer.wrap(bName));
        }
    }

    static long crc(ByteBuffer raw) throws IOException {
        ByteBuffer raw0 = raw.slice();
        CRC32 crc32 = new CRC32();
        if (CRC32_update != null) {
            try {
                CRC32_update.invoke(crc32, raw0);
            } catch (IllegalAccessException var5) {
                IllegalAccessException e = var5;
                throw new IOException(e);
            } catch (InvocationTargetException var6) {
                InvocationTargetException e = var6;
                Throwable t = e.getTargetException();
                if (t instanceof RuntimeException) {
                    throw (RuntimeException)t;
                }

                throw new IOException(t);
            }
        } else if (!raw.isDirect()) {
            crc32.update(raw0.array(), raw0.arrayOffset() + raw0.position(), raw0.remaining());
        } else {
            byte[] buff = new byte[4096];

            while(raw0.hasRemaining()) {
                int remain = Math.min(buff.length, raw0.remaining());
                raw0.get(buff, 0, remain);
                crc32.update(buff, 0, remain);
            }
        }

        return crc32.getValue();
    }

    static void inflate(ByteBuffer in, ByteBuffer out) throws DataFormatException, IOException {
        Inflater inf = new Inflater(true);
        int c;
        if (Inflater_setInput == null && in.isDirect()) {
            c = Math.max(4096, (int)Math.min((long)in.remaining(), 65535L));
            byte[] buffer = new byte[c];

            while(in.hasRemaining()) {
                int p = Math.min(c, in.remaining());
                in.get(buffer, 0, p);
                inf.setInput(buffer, 0, p);

                while(out.hasRemaining()) {
                    c = inf.inflate(out.array(), out.arrayOffset() + out.position(), out.remaining());
                    if (c <= 0) {
                        break;
                    }

                    out.position(out.position() + c);
                }

                if (inf.finished() || inf.needsDictionary()) {
                    break;
                }

                if (inf.needsInput() && !in.hasRemaining()) {
                    throw new EOFException("Unexpected end of ZLIB input stream");
                }
            }
        } else {
            if (Inflater_setInput != null) {
                try {
                    Inflater_setInput.invoke(inf, in);
                } catch (IllegalAccessException var9) {
                    reThrow(var9);
                } catch (InvocationTargetException var10) {
                    reThrow(var10);
                }
            } else if (!in.isDirect()) {
                inf.setInput(in.array(), in.arrayOffset() + in.position(), in.remaining());
            }

            if (Inflater_inflate != null) {
                try {
                    Inflater_inflate.invoke(inf, out);
                } catch (IllegalAccessException var7) {
                    reThrow(var7);
                } catch (InvocationTargetException var8) {
                    reThrow(var8);
                }
            } else if (!in.isDirect()) {
                c = inf.inflate(out.array(), out.arrayOffset() + out.position(), out.remaining());
                out.position(out.position() + c);
            }

            if (!inf.finished() && !inf.needsDictionary() && inf.needsInput()) {
                throw new EOFException("Unexpected end of ZLIB input stream");
            }
        }

    }

    static void inflate(ByteBuffer in, CRC32 crc, FileChannel outChannel) throws DataFormatException, IOException {
        Inflater inf = new Inflater(true);
        int bufSize = Math.max(4096, (int)Math.min((long)in.remaining(), 65535L));
        byte[] buffer = new byte[bufSize];
        ByteBuffer out = ByteBuffer.allocate(bufSize * 2);

        while(in.hasRemaining()) {
            int p = Math.min(bufSize, in.remaining());
            in.get(buffer, 0, p);
            inf.setInput(buffer, 0, p);

            while(true) {
                out.limit(out.capacity());
                out.rewind();
                int c = inf.inflate(out.array(), out.arrayOffset() + out.position(), out.remaining());
                if (c <= 0) {
                    if (inf.finished() || inf.needsDictionary()) {
                        return;
                    }

                    if (inf.needsInput() && !in.hasRemaining()) {
                        throw new EOFException("Unexpected end of ZLIB input stream");
                    }
                    break;
                }

                out.limit(c);
                if (crc != null) {
                    out.rewind();
                    crc.update(out.array(), 0, c);
                }

                out.rewind();
                outChannel.write(out);
            }
        }

    }

    private static void reThrow(Throwable t) throws DataFormatException, IOException {
        if (t instanceof DataFormatException) {
            throw (DataFormatException)t;
        } else if (t instanceof RuntimeException) {
            throw (RuntimeException)t;
        } else {
            throw new IOException(t);
        }
    }

    public void copy(FastZipIn zipIn, List<FastZipEntry> entries) throws IOException {
        if (entries == null) {
            entries = zipIn.entries();
        }

        this.copy((Source)zipIn, entries);
    }

    public static void copySTORED(Source source, FastZipEntry entry, FileChannel channel) throws IOException, DataFormatException {
        ByteBuffer raw = source.getRaw(entry);
        if (entry.compressionMethod == 0) {
            long crc32Value = crc(raw);
            if (crc32Value != entry.crc) {
                throw new IOException("crc mismatch on inflated file: " + crc32Value + " vs " + entry.crc);
            }

            channel.write(raw);
        } else {
            CRC32 crc = new CRC32();
            inflate(raw, crc, channel);
            long crc32Value = crc.getValue();
            if (crc32Value != entry.crc) {
                throw new IOException("crc mismatch on inflated file: " + crc32Value + " vs " + entry.crc);
            }

            if (raw.hasRemaining()) {
                throw new IOException("Size mismatch on inflated file: " + raw.position() + " vs " + entry.unCompressSize);
            }
        }

    }

    public void copyPart(Source source, List<FastZipEntry> entries) throws IOException {
        Iterator var3 = entries.iterator();

        while(var3.hasNext()) {
            FastZipEntry e = (FastZipEntry)var3.next();
            FastZipEntry freshEntry = e.clone();
            this.freshEntries.add(freshEntry);
            freshEntry.localHeaderRelOffset = this.outChannel.position();
            int aligment = 1;
            boolean forceStored = false;
            if (e.compressionMethod == 0) {
                aligment = 4;
            }

            try {
                if (this.isStorage4K(e)) {
                    aligment = 4096;
                    forceStored = true;
                    freshEntry.compressionMethod = 0;
                    freshEntry.compressedSize = freshEntry.unCompressSize;
                }

                if (this.targetSdk >= 30 && e.utf8Name().equals("resources.arsc")) {
                    aligment = 4;
                    forceStored = true;
                    freshEntry.compressionMethod = 0;
                    freshEntry.compressedSize = freshEntry.unCompressSize;
                }
            } catch (Exception var10) {
            }

            localFileHeader(freshEntry, this.outChannel, aligment);
            if (forceStored) {
                try {
                    copySTORED(source, e, this.outChannel);
                } catch (DataFormatException var9) {
                    DataFormatException dataFormatException = var9;
                    throw new IOException(dataFormatException);
                }
            } else {
                this.outChannel.write(source.getRaw(e));
            }
        }

    }

    protected boolean isStorage4K(FastZipEntry e) {
        return false;
    }

    public void copyEnd() throws IOException {
        long cdr = this.outChannel.position();
        Iterator var3 = this.freshEntries.iterator();

        while(var3.hasNext()) {
            FastZipEntry e = (FastZipEntry)var3.next();
            ceFileHeader(e, this.outChannel);
        }

        long sizeofcdr = this.outChannel.position() - cdr;
        ByteBuffer b = ByteBuffer.allocate(22).order(ByteOrder.LITTLE_ENDIAN);
        b.putInt(101010256);
        b.putShort((short)0);
        b.putShort((short)0);
        b.putShort((short)this.freshEntries.size());
        b.putShort((short)this.freshEntries.size());
        b.putInt((int)sizeofcdr);
        b.putInt((int)cdr);
        b.putShort((short)0);
        if (b.hasRemaining()) {
            throw new RuntimeException();
        } else {
            b.rewind();
            this.outChannel.write(b);
        }
    }

    public void copy(Source source, List<FastZipEntry> entries) throws IOException {
        this.copyPart(source, entries);
        this.copyEnd();
    }

    public void close() throws IOException {
        this.raf.close();
    }

    static {
        try {
            Inflater_setInput = Inflater.class.getDeclaredMethod("setInput", ByteBuffer.class);
            Inflater_inflate = Inflater.class.getDeclaredMethod("inflate", ByteBuffer.class);
            Inflater_setInput.setAccessible(true);
            Inflater_inflate.setAccessible(true);
        } catch (NoSuchMethodException var2) {
        }

        try {
            CRC32_update = CRC32.class.getDeclaredMethod("update", ByteBuffer.class);
        } catch (NoSuchMethodException var1) {
        }

    }
}
